//package crud;
//
//import anotaciones.Columna;
//import utilidades.Conexion;
//import java.lang.reflect.Field;
//import java.sql.Connection;
//import java.sql.PreparedStatement;
//import java.sql.ResultSet;
//import java.sql.SQLException;
//import java.util.ArrayList;
//import java.util.List;
//
///**
// *
// * @author wiland
// */
//public class Crud implements ICrud {
//
//    private StringBuilder sentencia;
//    private StringBuilder sentenciaP2;
//    private ArrayList valores;
//    private boolean primero = true;
//    private boolean isConexionExterna = false;
//    private String coma = ", ";
//    private Columna col;
//    
//    //Variables para funciones obligadas de interfaz
//    private Connection con;
//    private int posicion = 0;
//    private int cantidad = 0;
//    private int filas = 0;
//
//    @Override
//    public int save() {
//        filas = this.update();
//        if (filas > 0) {
//            return filas;
//        }
//        return this.insert();
//    }
//
//    @Override
//    public int insert() {
//        primero = true;
//        sentencia = new StringBuilder();
//        sentenciaP2 = new StringBuilder();
//        valores = new ArrayList();
//        sentencia.append("INSERT INTO ");
//        sentencia.append(this.getClass().getSimpleName() + " (");
//        sentenciaP2.append(") VALUES (");
//
//        Field[] campos = this.getClass().getDeclaredFields();
//
//        for (Field campo : campos) {
//            try {
//                col = campo.getAnnotation(Columna.class);
//                if (col == null || col.AI()) {
//                    continue;
//                }
//                sentencia.append(primero ? "" : coma);
//                sentencia.append(campo.getName());
//
//                sentenciaP2.append(primero ? "" : coma);
//                sentenciaP2.append("?");
//
//                campo.setAccessible(true);
//                valores.add(campo.get(this));
//                primero = false;
//            } catch (IllegalArgumentException ex) {
//                ex.printStackTrace();
//            } catch (IllegalAccessException ex) {
//                ex.printStackTrace();
//            }
//        }
//        sentenciaP2.append(")");
//        sentencia.append(sentenciaP2.toString());
//
//        return (execute(sentencia.toString(), valores.toArray()));
//    }
//
//    @Override
//    public int update() {
//        boolean primeroMod, primeroCon;
//        String condicion = "";
//        ArrayList vblesMod = new ArrayList(), vblesCon = new ArrayList();
//        sentencia = new StringBuilder();
//        valores = new ArrayList();
//        sentencia.append("UPDATE ");
//        sentencia.append(this.getClass().getSimpleName());
//        sentencia.append(" SET ");
//        primeroMod = primeroCon = true;
//
//        Field[] campos = this.getClass().getDeclaredFields();
//        for (Field campo : campos) {
//            try {
//                col = campo.getAnnotation(Columna.class);
//                if (col == null) {
//                    continue;
//                }
//
//                campo.setAccessible(true);
//                if (!col.PK()) {
//                    sentencia.append(primeroMod ? "" : coma);
//                    sentencia.append(campo.getName() + " = ?");
//                    vblesMod.add(campo.get(this));
//                    primeroMod = false;
//                } else {
//                    condicion += primeroCon ? " " : coma;
//                    condicion += campo.getName() + " = ?";
//                    vblesCon.add(campo.get(this));
//                    primeroCon = false;
//                }
//                primero = false;
//            } catch (IllegalArgumentException ex) {
//                ex.printStackTrace();
//            } catch (IllegalAccessException ex) {
//                ex.printStackTrace();
//            }
//        }
//
//        sentencia.append(" WHERE" + condicion);
//        valores.addAll(vblesMod);
//        valores.addAll(vblesCon);
//
//        return (execute(sentencia.toString(), valores.toArray()));
//    }
//
//    @Override
//    public int delete() {
//        sentencia = new StringBuilder();
//        valores = new ArrayList();
//        sentencia.append("DELETE FROM ");
//        sentencia.append(this.getClass().getSimpleName());
//        sentencia.append(" WHERE ");
//        primero = true;
//
//        Field[] campos = this.getClass().getDeclaredFields();
//        for (Field campo : campos) {
//            try {
//                col = campo.getAnnotation(Columna.class);
//                if (col == null) {
//                    continue;
//                }
//
//                if (col.PK()) {
//                    sentencia.append(primero ? "" : " AND ");
//                    sentencia.append(campo.getName() + " = ?");
//                    campo.setAccessible(true);
//                    valores.add(campo.get(this));
//                    primero = false;
//                }
//            } catch (IllegalArgumentException ex) {
//                ex.printStackTrace();
//            } catch (IllegalAccessException ex) {
//                ex.printStackTrace();
//            }
//        }
//
//        return (execute(sentencia.toString(), valores.toArray()));
//    }
//
//    @Override
//    public List<? extends ICrud> select() {
//        boolean primeroWhere = true;
//        sentencia = new StringBuilder();
//        sentenciaP2 = new StringBuilder();
//        valores = new ArrayList();
//        sentencia.append("SELECT ");
//        sentenciaP2.append(" FROM " + this.getClass().getSimpleName() + " ");
//        primero = true;
//
//        Field[] campos = this.getClass().getDeclaredFields();
//        for (Field campo : campos) {
//            try {
//                col = campo.getAnnotation(Columna.class);
//                if (col == null) {
//                    continue;
//                }
//                sentencia.append(primero ? "" : coma);
//                sentencia.append(campo.getName());
//                campo.setAccessible(true);
//                if (campo.get(this) != null) {
//                    if (primeroWhere) {
//                        sentenciaP2.append("WHERE ");
//                    }
//                    sentenciaP2.append(primeroWhere ? "" : " AND ");
//                    sentenciaP2.append(campo.getName() + " = ?");
//
//                    valores.add(campo.get(this));
//                    primeroWhere = false;
//                }
//                primero = false;
//            } catch (IllegalArgumentException ex) {
//                ex.printStackTrace();
//            } catch (IllegalAccessException ex) {
//                ex.printStackTrace();
//            }
//        }
//
//        sentencia.append(sentenciaP2.toString());
//
//        return (select(sentencia.toString(), valores.toArray()));
//    }
//
//    @Override
//    public List<? extends ICrud> select(String sql, Object... valores) {
//        ResultSet res = null;
//        PreparedStatement cmd = null;
//        Crud obj;
//        ArrayList<Crud> lista = new ArrayList();
//
//        try {
//            get_Conexion();
//
//            cmd = con.prepareStatement(sql, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
//            int i = 1;
//
//            for (Object valor : valores) {
//                cmd.setObject(i, valor);
//                i++;
//            }
//
//            res = cmd.executeQuery();
//            res.absolute(this.posicion);
//            res.setFetchSize(this.cantidad);
//            
//            i = 0;
//            
//            while (res.next()) {
//                if (this.cantidad != 0 && i >= this.cantidad) {
//                    break;
//                }
//                obj = this.getClass().newInstance();
//                for (Field attr : obj.getClass().getDeclaredFields()) {
//                    col = attr.getAnnotation(Columna.class);
//                    if (col == null) {
//                        continue;
//                    }
//                    attr.setAccessible(true);
//                    attr.set(obj, res.getObject(attr.getName()));
//                }
//                lista.add(obj);
//                i++;
//            }
//            
//            res.last();
//            this.filas = res.getRow();
//
//        } catch (SQLException ex) {
//            System.out.println("Error en la ejecución de la operación: " + ex.toString());
//        } catch (InstantiationException ex) {
//            System.out.println("Error en la instanciación de la clase: " + ex.toString());
//        } catch (IllegalAccessException ex) {
//            System.out.println("Error de acceso a los campos: " + ex.toString());
//        } finally {
//            try {
//                if (res != null) {
//                    res.close();
//                }
//                if (cmd != null) {
//                    cmd.close();
//                }
//                if (con != null && !isConexionExterna) {
//                    con.close();
//                }
//            } catch (SQLException ex) {
//                System.out.println("No se pudieron cerrar los canales: " + ex.toString());
//            }
//        }
//
//        this.filas = lista.size();
//        return lista;
//    }
//
//    @Override
//    public int execute(String sql, Object... parametros) {
//        int res = 0;
//        PreparedStatement cmd = null;
//
//        try {
//            get_Conexion();
//            
//            cmd = con.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
//            int i = 1;
//
//            for (Object valor : parametros) {
//                cmd.setObject(i, valor);
//                i++;
//            }
//
//            res = cmd.executeUpdate();
//
//            ResultSet rs = cmd.getGeneratedKeys();
//            if (rs.next()) {
//                for (Field attr : this.getClass().getDeclaredFields()) {
//                    col = attr.getAnnotation(Columna.class);
//                    if (col == null && !col.AI()) {
//                        continue;
//                    }
//                    attr.setAccessible(true);
//                    try {
//                        attr.set(this, rs.getObject(attr.getName()));
//                    } catch (Exception ex) {
//                        ex.printStackTrace();
//                    }
//                }
//            }
//        } catch (SQLException ex) {
//            System.out.println("Error en la ejecución de la operación: " + ex.toString());
//        } finally {
//            try {
//                if (cmd != null) {
//                    cmd.close();
//                }
//                if (con != null && !isConexionExterna) {
//                    con.close();
//                    con = null;
//                }
//            } catch (SQLException ex) {
//                System.out.println("No se pudieron cerrar los canales: " + ex.toString());
//            }
//        }
//
//        return res;
//    }
//
//    @Override
//    public String get_Tabla() {
//        return this.getClass().getSimpleName();
//    }
//
//    @Override
//    public Connection get_Conexion() {
//        if (!isConexionExterna) {
//            Conexion c = new Conexion();
//            con = c.getConexion();
//        }
//        return this.con;
//    }
//
//    @Override
//    public void set_Conexion(Connection Conexion) {
//        isConexionExterna = true;
//        this.con = Conexion;
//    }
//
//    @Override
//    public boolean isConexionExterna() {
//        return this.isConexionExterna;
//    }
//
//    @Override
//    public int get_Posicion() {
//        return this.posicion;
//    }
//
//    @Override
//    public void set_Posicion(int posicion) {
//        this.posicion = posicion;
//    }
//
//    @Override
//    public int get_Cantidad() {
//        return this.cantidad;
//    }
//
//    @Override
//    public void set_Cantidad(int cantidad) {
//        this.cantidad = cantidad;
//    }
//
//    @Override
//    public int get_Filas() {
//        return this.filas;
//    }
//}

































/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package crud ;

import anotaciones.Columna;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import utilidades.Conexion;

public class Crud implements ICrud {

    private int posicion;
    private int cantidad;
    private boolean externa = false;
    private Connection con;
    private int filas = 0;

    @Override
    public int insert() {
        String sql = "INSERT INTO " + get_Tabla() + " (";
        String condiciones = "";
        ArrayList valores = new ArrayList();
        Columna col;
        for (Field attr : this.getClass().getDeclaredFields()) {
            col = attr.getAnnotation(Columna.class);
            if (col == null || col.AI()) {
                continue;
            }
            sql = sql + attr.getName() + ",";
            try {
                attr.setAccessible(true);
                valores.add(attr.get(this));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }

        sql = sql.substring(0, sql.length() - 1);
        sql = sql + ") VALUES (";
        for (Object p : valores) {
            sql = sql + "?,";
        }
        sql = sql.substring(0, sql.length() - 1);

        sql = sql + ")";

        System.out.println(sql);
//        return 0;
        return execute(sql, valores.toArray());
    }

    @Override
    public int update() {
        String sql = "UPDATE " + get_Tabla() + " SET ";
        String con = "";
        Columna col;
        ArrayList valores = new ArrayList();
        ArrayList valorescon = new ArrayList();
        for (Field p : this.getClass().getDeclaredFields()) {
            try {
                p.setAccessible(true);
                col = p.getAnnotation(Columna.class);
                if (col != null && col.PK()) {
                    con = con + p.getName() + "=? and ";
                    valorescon.add(p.get(this));
                    continue;
                }
                if (p.get(this) != null) {
                    sql = sql + p.getName() + "=?, ";
                    valores.add(p.get(this));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        sql = sql.substring(0, sql.length() - 2);
        sql = sql + " WHERE " + con.substring(0, con.length() - 4);

        for (Object p : valorescon) {
            valores.add(p);
        }

//        System.out.println(sql);
//        return 0;
        return execute(sql, valores.toArray());
    }

    @Override
    public int delete() {
        String sql = "delete from " + get_Tabla();
        String condiciones = "";
        ArrayList valores = new ArrayList();
        Columna col;
        for (Field attr : this.getClass().getDeclaredFields()) {
            col = attr.getAnnotation(Columna.class);
            if (col == null || !col.PK()) {
                continue;
            }
            condiciones += "and " + attr.getName() + "= ? ";
            try {
                attr.setAccessible(true);
                valores.add(attr.get(this));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        sql = sql + (condiciones.isEmpty() ? "" : " where " + condiciones.substring(4));
//        System.out.println(sql);
//        return 0;
        return execute(sql, valores.toArray());
    }
    
    
    
    
    
    
    
    
    
     @Override
    public int execute(String sql, Object... parametros) {
        int r = 0;
        PreparedStatement cmd = null;
        try {
            con=new Conexion().getConexion();
            cmd = con.prepareStatement(sql);
            for (int i = 0; i < parametros.length; i++) {
                cmd.setObject(i + 1, parametros[i]);
            }
            r = cmd.executeUpdate();

            
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {

//            rs.close();
                cmd.close();
                if (!isConexionExterna()) {
                    con.close();
                    con = null;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return r;
    }

    @Override
    public int save() {
        Columna col;
        for (Field f : this.getClass().getDeclaredFields()) {
            try {
                f.setAccessible(true);
                col = f.getAnnotation(Columna.class);
                if (col != null && col.PK()) {
                    if (f.get(this) != null) {
                        int r = update();
                        if (r == 0) {
                            return insert();
                        } else {
                            return r;
                        }
                    } else {
                        return insert();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return 0;
    }

    @Override
    public List<? extends ICrud> select() {
        String sql = "SELECT ";
        String con = "";
        ArrayList valores = new ArrayList();
        ArrayList valorescon = new ArrayList();
        Columna col;

        for (Field p : this.getClass().getDeclaredFields()) {
            try {
                p.setAccessible(true);
                col = p.getAnnotation(Columna.class);
                if ((col != null)) {
                    if (p.get(this) != null) {
                        con = con + p.getName() + "=? and ";
                        valorescon.add(p.get(this));
                    }
                    sql = sql + p.getName() + ",";
                }
                valores.add(p.get(this));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        sql = sql.substring(0, sql.length() - 1);
        if (con.isEmpty()) {
            sql = sql + " FROM " + get_Tabla() ;
//            System.out.println(sql);
        } else {
            sql = sql + " FROM " + get_Tabla() + " WHERE " + con.substring(0, con.length() - 4);
//            System.out.println(sql);
        }
        for (Object p : valorescon) {
            valores.add(p);
//            System.out.println(p.toString());
        }
        System.out.println(sql);
        return select(sql, valorescon.toArray());
    }

    @Override
    public List<? extends ICrud> select(String sql, Object... params) {
        int r = 0;
//        Connection con;
        PreparedStatement cmd = null;
        ResultSet rs = null;
        Columna col;
        ArrayList<ICrud> list = new ArrayList<ICrud>();
        ICrud objeto;
        try {
            con = new Conexion().getConexion();
//            cmd = con.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            cmd = con.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                cmd.setObject(i + 1, params[i]);
            }
            rs = cmd.executeQuery();
//            rs.last();
//            filas = rs.getRow();
            while (rs.next()) {
                objeto = this.getClass().newInstance();
                for (Field attr : objeto.getClass().getDeclaredFields()) {
                    col = attr.getAnnotation(Columna.class);
                    attr.setAccessible(true);
                    if ((col != null)) {
                        Object valor = rs.getObject(attr.getName());
                        attr.set(objeto, valor);
                    }

                }
                list.add(objeto);
            }



        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {

                rs.close();
                cmd.close();
                if (!isConexionExterna()) {
                    con.close();
                    con = null;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return list;
    }

    @Override
    public String get_Tabla() {
        return this.getClass().getSimpleName();
    }

    @Override
    public Connection get_Conexion() {
        if (!isConexionExterna() && con == null) {
            Conexion c = new Conexion();
            con = c.getConexion();
//            con = new CONEXION().getConexionHome();
//            con = new CONEXION().getConexionCes();
            externa = false;
        }
        return con;
    }

    @Override
    public void set_Conexion(Connection Conexion) {
        externa = true;
        con = Conexion;
    }

    @Override
    public boolean isConexionExterna() {
        return externa;
    }

    @Override
    public int get_Posicion() {
        return this.posicion;
    }

    @Override
    public void set_Posicion(int posicion) {
        this.posicion = posicion;

    }

    @Override
    public int get_Cantidad() {
        return this.cantidad;
    }

    @Override
    public void set_Cantidad(int cantidad) {
        this.cantidad = cantidad;
    }

    @Override
    public int get_Filas() {
        return filas;
    }
}
